package com.xiumu.common.core.tree;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.lang.tree.parser.DefaultNodeParser;
import cn.hutool.core.util.StrUtil;

import java.util.List;
import java.util.Map;

/**
 * 树形结构构造工具
 *
 * @Author XiuMu
 * @Date 2022/7/16
 */
public class XiuMuTreeUtil extends TreeUtil {

    /**
     * 构造树形结构
     *
     * @param objectList 对象数组
     * @param parentId   最顶层父节点ID
     * @return List<Tree<Long>>
     */
    public static List<Tree<Long>> buildTree(List<?> objectList, Long parentId) {
        return buildTree(objectList, parentId, ofKeys(null, null, null, null));
    }

    /**
     * 构造树形结构
     *
     * @param objectList 对象数组
     * @param parentId   最顶层父节点ID
     * @param config     配置类
     * @return List<Tree<Long>>
     */
    public static List<Tree<Long>> buildTree(List<?> objectList, Long parentId, TreeNodeConfig config) {
        List<TreeNode<Long>> nodeList = CollUtil.newArrayList();
        // 将对象转化成树节点
        for (Object obj : objectList) {
            Map<String, Object> bean = BeanUtil.beanToMap(obj);
            final Long id = Convert.toLong(bean.get(config.getIdKey()));
            final Long objParentId = Convert.toLong(bean.get(config.getParentIdKey()));
            final Long weight = Convert.toLong(bean.get(config.getWeightKey()));
            final String name = Convert.toStr(bean.get(config.getNameKey()));
            nodeList.add(new TreeNode<Long>(id, objParentId, name, weight).setExtra(bean));
        }
        return build(nodeList, parentId, config, new DefaultNodeParser<>());
    }

    /**
     * 配置节点ID的 key
     * 该方法用来设置需要构建树形结构的对象的，节点 父节点，排序字段 key，默认是 id, parentId, weight
     * 如果有的对象是根据其他字段 key 构建树，如 code， parentCode， sort
     * 就可以先设置 key TreeNodeConfig config = XiuMuTreeUtil.ofKeys("code", "parentCode", "sort", "name")
     * 再调用 XiuMuTreeUtil.buildTree(objectList, parentCodeValue, config)
     *
     * @param idKey       节点ID
     * @param parentIdKey 父节点ID
     * @param weightKey   权重
     */
    public static TreeNodeConfig ofKeys(String idKey, String parentIdKey, String weightKey, String nameKey) {
        return new TreeNodeConfig()
                .setIdKey(StrUtil.isNotBlank(idKey) ? idKey : "id")
                .setParentIdKey(StrUtil.isNotBlank(parentIdKey) ? parentIdKey : "parentId")
                .setWeightKey(StrUtil.isNotBlank(weightKey) ? weightKey : "weight")
                .setNameKey(StrUtil.isNotBlank(nameKey) ? nameKey : "name")
                ;
    }
}
